package com.strategy.manager;


import jakarta.annotation.PostConstruct;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import com.strategy.core.AbstractStrategy;
import com.strategy.core.BaseStrategy;
import com.strategy.core.CompositeStrategy;
import com.strategy.entity.StrategyEntity;
import com.strategy.exception.StrategyNotFoundException;
import com.strategy.service.StrategyService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 策略管理器，负责策略的注册、获取和执行
 */
@Slf4j
@Component
public class StrategyManager implements ApplicationContextAware {

    // 策略存储Map: key = strategyKey:version, value = 策略实例
    private final Map<String, BaseStrategy<?, ?, ?>> strategyMap = new ConcurrentHashMap<>();

    private final StrategyService strategyService;
    @Getter
    private ApplicationContext applicationContext;

    public StrategyManager(StrategyService strategyService) {
        this.strategyService = strategyService;
    }

    /**
     * 初始化方法，从数据库加载策略
     */
    @PostConstruct
    public void init() {
        // 1. 从数据库加载所有启用的策略
        List<StrategyEntity> strategyEntities = strategyService.list();
        for (StrategyEntity entity : strategyEntities) {
            if (entity.getStatus() == 1) { // 状态为启用
                try {
                    loadAndRegisterStrategy(entity);
                } catch (Exception e) {
                    log.error("加载策略失败: {}", entity, e);
                }
            }
        }
        log.info("策略管理器初始化完成，共加载 {} 个策略", strategyMap.size());
    }

    /**
     * 从Spring容器中自动注册带@Strategy注解的策略
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;

        // 获取所有策略实现类
        Map<String, BaseStrategy> strategyBeans = applicationContext.getBeansOfType(BaseStrategy.class);
        for (BaseStrategy strategy : strategyBeans.values()) {
            try {
                registerStrategy(strategy, false);
            } catch (Exception e) {
                log.error("注册策略bean失败: {}", strategy, e);
            }
        }
    }

    /**
     * 注册策略
     */
    public void registerStrategy(BaseStrategy<?, ?, ?> strategy, boolean persist) {
        String key = strategy.getKey();
        String version = strategy.getVersion();
        String mapKey = generateMapKey(key, version);

        strategyMap.put(mapKey, strategy);
        log.info("策略注册成功: key={}, version={}", key, version);

        // 如果需要持久化，保存到数据库
        if (persist) {
            StrategyEntity entity = new StrategyEntity();
            entity.setStrategyKey(key);
            entity.setVersion(version);
            entity.setDescription(strategy.getDescription());
            entity.setClassName(strategy.getClass().getName());
            entity.setStatus(1); // 启用
            entity.setIsDefault(false);

            // 检查是否已有该策略
            List<StrategyEntity> exist = strategyService.getByStrategyKey(key);
            if (exist.stream().anyMatch(e -> e.getVersion().equals(version))) {
                // 已存在，更新
                StrategyEntity existEntity = exist.stream()
                        .filter(e -> e.getVersion().equals(version))
                        .findFirst().orElse(null);
                if (existEntity != null) {
                    entity.setId(existEntity.getId());
                    entity.setIsDefault(existEntity.getIsDefault());
                }
            } else {
                // 新策略，如果是第一个版本则设为默认
                if (exist.isEmpty()) {
                    entity.setIsDefault(true);
                }
            }

            strategyService.registerStrategy(entity);
        }
    }

    /**
     * 注册组合策略
     */
    public void registerCompositeStrategy(CompositeStrategy<?, ?, ?> compositeStrategy, boolean persist) {
        registerStrategy(compositeStrategy, persist);
    }

    /**
     * 移除策略
     */
    public void unregisterStrategy(String key, String version, boolean persist) {
        String mapKey = generateMapKey(key, version);
        strategyMap.remove(mapKey);
        log.info("策略移除成功: key={}, version={}", key, version);

        // 如果需要从数据库删除
        if (persist) {
            List<StrategyEntity> strategies = strategyService.getByStrategyKey(key);
            strategies.stream()
                    .filter(s -> s.getVersion().equals(version))
                    .findFirst()
                    .ifPresent(s -> strategyService.removeById(s.getId()));
        }
    }

    /**
     * 根据key和version获取策略
     */
    @SuppressWarnings("unchecked")
    public <T, P, R> BaseStrategy<T, P, R> getStrategy(String key, String version) {
        String mapKey = version != null ? generateMapKey(key, version) : getDefaultMapKey(key);

        BaseStrategy<?, ?, ?> strategy = strategyMap.get(mapKey);
        if (strategy == null) {
            throw new StrategyNotFoundException("策略不存在: key=" + key + ", version=" + version);
        }

        return (BaseStrategy<T, P, R>) strategy;
    }

    /**
     * 根据key获取默认版本策略
     */
    public <T, P, R> BaseStrategy<T, P, R> getStrategy(String key) {
        return getStrategy(key, null);
    }

    /**
     * 执行策略
     */
    public <T, P, R> R executeStrategy(String key, String version, T input, Map<String, P> params) {
        BaseStrategy<T, P, R> strategy = getStrategy(key, version);
        return strategy.execute(input, params);
    }

    /**
     * 执行默认版本策略
     */
    public <T, P, R> R executeStrategy(String key, T input, Map<String, P> params) {
        return executeStrategy(key, null, input, params);
    }

    /**
     * 获取所有策略key
     */
    public Map<String, List<String>> getAllStrategyKeys() {
        Map<String, List<String>> result = new HashMap<>();

        strategyMap.keySet().forEach(mapKey -> {
            String[] parts = mapKey.split(":");
            String key = parts[0];
            String version = parts[1];

            result.computeIfAbsent(key, k -> new java.util.ArrayList<>()).add(version);
        });

        return result;
    }

    /**
     * 生成Map的key
     */
    private String generateMapKey(String key, String version) {
        return key + ":" + version;
    }

    /**
     * 获取默认版本的Map key
     */
    private String getDefaultMapKey(String key) {
        StrategyEntity defaultStrategy = strategyService.getDefaultByKey(key);
        if (defaultStrategy == null) {
            throw new StrategyNotFoundException("策略不存在默认版本: key=" + key);
        }
        return generateMapKey(key, defaultStrategy.getVersion());
    }

    /**
     * 加载并注册策略
     */
    private void loadAndRegisterStrategy(StrategyEntity entity) throws Exception {
        // 反射创建策略实例
        Class<?> strategyClass = ClassUtils.forName(entity.getClassName(), this.getClass().getClassLoader());
        BaseStrategy<?, ?, ?> strategy = (BaseStrategy<?, ?, ?>) strategyClass.getDeclaredConstructor().newInstance();

        // 设置策略信息
        if (strategy instanceof AbstractStrategy<?, ?, ?> abstractStrategy) {
            abstractStrategy.setKey(entity.getStrategyKey());
            abstractStrategy.setVersion(entity.getVersion());
            abstractStrategy.setDescription(entity.getDescription());
        }

        // 注册策略
        strategyMap.put(generateMapKey(entity.getStrategyKey(), entity.getVersion()), strategy);
    }

}
